﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using AsmFromGpp;
using LevenshteinDistance;
using LexicalAnalysisCs;
using TextDiffAlgoCs;

namespace UI
{
    public static class CompareManager
    {
        private static void SetFontColor(RichTextBox rtb, int startPos, int len, Color c/*, Font f*/)
        {
            rtb.Select(startPos, len);
            rtb.SelectionColor = c;
            rtb.SelectionFont = new Font("Inconsolata", 11);
            rtb.SelectionLength = 0;
        }

        public static void TextCompareBegin(RichTextBox rtb1, RichTextBox rtb2, Label lbl)
        {
//             CompareResult cr = new CompareResult();
//             double dg = cr.GetCompareRes(rtb1.Text, rtb2.Text);
// //            lbl.Text = "Similarity Degree:" + String.Format("{0:F2}", Levenshtein.SimDegree(rtb1.Text, rtb2.Text) * 100.0) + "%";
// //            lbl.Text = "Similarity Degree:" + String.Format("{0:F2}", (double)Levenshtein.GetSimilarityWith(richTextBox1.Text, richTextBox2.Text) * 100.0) + "%";
//             lbl.Text = "Similarity Degree:" + String.Format("{0:F2}", dg * 100.0) + "%";
// 
//             List<TextDiff> diffList = cr.getDiffList;
            List<TextDiff> diffList = TextComparer.Compare(rtb1.Text, rtb2.Text);
            SetFontColor(rtb1, 0, rtb1.Text.Length, Color.Blue);
            SetFontColor(rtb2, 0, rtb2.Text.Length, Color.Blue);

            foreach (var td in diffList)
            {
                switch (td.getDiffType)
                {
                    case TextDiff.TYPE_DELETE:
                        SetFontColor(rtb1, td.getDiffStartIndex, td.getDiffLength, Color.Red);
                        break;
                    case TextDiff.TYPE_INSERT:
                        SetFontColor(rtb2, td.getDiffStartIndex, td.getDiffLength, Color.Red);
                        break;
//                     case TextDiff.TYPE_SAME_A:
//                         setFontColor(richTextBox1, td.getDiffStartIndex, td.getDiffLength + 1, Color.Blue);
//                         break;
//                     case TextDiff.TYPE_SAME_B:
//                         setFontColor(richTextBox2, td.getDiffStartIndex, td.getDiffLength + 1, Color.Blue);
//                         break;
                    default:
                        break;
                }
            }
        }

        public static void Test(RichTextBox rtb1, RichTextBox rtb2, Label lbl)
        {
            FileStream fs = new FileStream("inFile.tmp", FileMode.OpenOrCreate);
            StreamWriter sw = new StreamWriter(fs);
            sw.Write(rtb1.Text);
            sw.Close();
            fs.Close();

            SetFontColor(rtb1, 0, rtb1.Text.Length, Color.Green);

            LexicalAnalyzerCs lac = new LexicalAnalyzerCs("inFile.tmp", "outFile.tmp");
            List<LexicalAnalyzerCs.StrInt> resList = lac.getResList;

            bool t = false;
            foreach (var rl in resList)
            {
                if (t)
                {
                    SetFontColor(rtb1, rl.mEndIndex - rl.mContent.Length, rl.mContent.Length, Color.Blue);
                }
                else
                {
                    SetFontColor(rtb1, rl.mEndIndex - rl.mContent.Length, rl.mContent.Length, Color.Red);
                }
                t = !t;
            }

            StringBuilder sb = new StringBuilder();
            foreach (var rl in resList)
            {
                sb.Append(rl.mEndIndex.ToString() + ' ' + rl.mContent + "\r\n");
            }
            rtb2.Text = sb.ToString();

            File.Delete(@"inFile.tmp");
            File.Delete(@"outFile.tmp");
        }

        private static void ShowResult(List<TextDiff> diffList, List<LexicalAnalyzerCs.StrInt> lst1, List<LexicalAnalyzerCs.StrInt> lst2, RichTextBox rtb1, RichTextBox rtb2)
        {
            foreach (var td in diffList)
            {
                switch (td.getDiffType)
                {
                    case TextDiff.TYPE_DELETE:
                        for (int i = 0; i < td.getDiffLength; i++)
                        {
                            SetFontColor(rtb1,
                                lst1[td.getDiffStartIndex + i].mEndIndex - lst1[td.getDiffStartIndex + i].mContent.Length,
                                lst1[td.getDiffStartIndex + i].mContent.Length,
                                Color.Red);
                        }
                        break;
                    case TextDiff.TYPE_INSERT:
                        for (int i = 0; i < td.getDiffLength; i++)
                        {
                            SetFontColor(rtb2,
                                lst2[td.getDiffStartIndex + i].mEndIndex - lst2[td.getDiffStartIndex + i].mContent.Length,
                                lst2[td.getDiffStartIndex + i].mContent.Length,
                                Color.Red);
                        }
                        break;
                    default:
                        break;
                }
            }
        }

        public static void ListCompareBegin(RichTextBox rtb1, RichTextBox rtb2, Label lbl)
        {
            // Create the tmp files so we can transfer the Cpp exe result into Cs projects.
            FileStream fs1 = new FileStream("inFile1.tmp", FileMode.OpenOrCreate);
            StreamWriter sw1 = new StreamWriter(fs1);
            sw1.Write(rtb1.Text);
            sw1.Close();
            fs1.Close();

            FileStream fs2 = new FileStream("inFile2.tmp", FileMode.OpenOrCreate);
            StreamWriter sw2 = new StreamWriter(fs2);
            sw2.Write(rtb2.Text);
            sw2.Close();
            fs2.Close();

            SetFontColor(rtb1, 0, rtb1.Text.Length, Color.Blue);
            SetFontColor(rtb2, 0, rtb2.Text.Length, Color.Blue);

            LexicalAnalyzerCs lac1 = new LexicalAnalyzerCs("inFile1.tmp", "outFile1.tmp");
            LexicalAnalyzerCs lac2 = new LexicalAnalyzerCs("inFile2.tmp", "outFile2.tmp");

            // Result of comparing #include
            List<LexicalAnalyzerCs.StrInt> includeList1 = lac1.GetIncludeFileNames(true);
            List<LexicalAnalyzerCs.StrInt> includeList2 = lac2.GetIncludeFileNames(true);
            List<TextDiff> includeDiffList = ListComparer.Compare(includeList1, includeList2);
            ShowResult(includeDiffList, includeList1, includeList2, rtb1, rtb2);

            // Result of comparing the using namespace;
            List<LexicalAnalyzerCs.StrInt> namespaceList1 = lac1.GetNamespaceName(true);
            List<LexicalAnalyzerCs.StrInt> namespaceList2 = lac2.GetNamespaceName(true);
            List<TextDiff> namespaceDiffList = ListComparer.Compare(namespaceList1, namespaceList2);
            ShowResult(namespaceDiffList, namespaceList1, namespaceList2, rtb1, rtb2);

            // Get the compare result showed.
            List<LexicalAnalyzerCs.StrInt> resList1 = lac1.getResList;
            List<LexicalAnalyzerCs.StrInt> resList2 = lac2.getResList;
            List<TextDiff> diffList = ListComparer.Compare(resList1, resList2);
            ShowResult(diffList, resList1, resList2, rtb1, rtb2);
//             List<LexicalAnalyzerCs.StrInt> wordsList1 = new List<LexicalAnalyzerCs.StrInt>();
//             List<LexicalAnalyzerCs.StrInt> wordsList2 = new List<LexicalAnalyzerCs.StrInt>();
//             List<LexicalAnalyzerCs.StrInt> symbolList1 = new List<LexicalAnalyzerCs.StrInt>();
//             List<LexicalAnalyzerCs.StrInt> symbolList2 = new List<LexicalAnalyzerCs.StrInt>();
//             lac1.GetWordsSymbolsList(ref wordsList1, ref symbolList1);
//             lac2.GetWordsSymbolsList(ref wordsList2, ref symbolList2);
//             List<TextDiff> wordsDiffList = ListComparer.Compare(wordsList1, wordsList2);
//             List<TextDiff> symbolDiffList = ListComparer.Compare(symbolList1, symbolList2);
//             ShowResult(wordsDiffList, wordsList1, wordsList2, rtb1, rtb2);
//             ShowResult(symbolDiffList, symbolList1, symbolList2, rtb1, rtb2);

            // Remember to delete the tmp files.
            File.Delete(@"inFile1.tmp");
            File.Delete(@"inFile2.tmp");
            File.Delete(@"outFile1.tmp");
            File.Delete(@"outFile2.tmp");
        }

        public static void AsmCompare(RichTextBox rtb1, RichTextBox rtb2, Label lbl)
        {
            FileStream fs1 = new FileStream("RichTextBox1.cpp", FileMode.Create);
            StreamWriter sw1 = new StreamWriter(fs1);
            sw1.Write(rtb1.Text + '\n');
            sw1.Close();
            fs1.Close();

            FileStream fs2 = new FileStream("RichTextBox2.cpp", FileMode.Create);
            StreamWriter sw2 = new StreamWriter(fs2);
            sw2.Write(rtb2.Text + '\n');
            sw2.Close();
            fs2.Close();

            CodeDecorating cd1 = new CodeDecorating("RichTextBox1.cpp", "rtb1Lex.out");
            CodeDecorating cd2 = new CodeDecorating("RichTextBox2.cpp", "rtb2Lex.out");
            cd1.InsertInlines();
            cd2.InsertInlines();
            cd1.OutputCodesToFile("RichTextBox1.cpp");
            cd2.OutputCodesToFile("RichTextBox2.cpp");

            int flag = 0;
            GenerateAsm ga1 = new GenerateAsm();
            GenerateAsm ga2 = new GenerateAsm();

            string tmp = ga1.GenAsmToFile("RichTextBox1.cpp");
            ga1.GenInstructionList();
            if (tmp == "")
            {
                rtb1.Text = ga1.MAsmCode;
//                 rtb1.Text = "";
//                 foreach (var gm in ga1.MAsmInstList)
//                 {
//                     rtb1.Text += gm.mContent;
//                     rtb1.Text += gm.mEndIndex.ToString() + '\n';
//                 }
                flag++;
            }
            else
            {
                rtb1.Text = tmp;
            }

            tmp = ga2.GenAsmToFile("RichTextBox2.cpp");
            ga2.GenInstructionList();
            if (tmp == "")
            {
                rtb2.Text = ga2.MAsmCode;
//                 rtb2.Text = "";
//                 foreach (var gm in ga2.MAsmInstList)
//                 {
//                     rtb2.Text += gm.mContent;
//                     rtb2.Text += gm.mEndIndex.ToString() + '\n';
//                 }
                flag++;
            }
            else
            {
                rtb2.Text = tmp;
            }

            if (flag == 2)
            {
                List<TextDiff> diffList = ListComparer.Compare(ga1.MAsmInstList, ga2.MAsmInstList);
                ShowResult(diffList, ga1.MAsmInstList, ga2.MAsmInstList, rtb1, rtb2);
            }

            File.Delete("RichTextBox1.cpp");
            File.Delete("RichTextBox2.cpp");
            File.Delete("RichTextBox1.cpp.asm");
            File.Delete("RichTextBox2.cpp.asm");
        }

    }
}

